//
// Created by 陈成 on 2020/2/11.
//

#include "InstFetcher.h"
#include "config.h"

InstFetcher::InstFetcher(sc_module_name name) : sc_module(name) {
    SC_THREAD(sendInst);

    FILE *fp = fopen(SIM_DATA_PATH "kernel.txt", "r");
    assert(fp != nullptr);

    icache = new unsigned char[10000];
    pc = 0;
    pc_max = 0;

    uint32_t inst, curr_addr = 0;
    while(fscanf(fp, "%x", &inst) != EOF) {
        icache[curr_addr + 0] = sc_bv<32>(inst).range(7,0).to_uint();
        icache[curr_addr + 1] = sc_bv<32>(inst).range(15,8).to_uint();
        icache[curr_addr + 2] = sc_bv<32>(inst).range(23,16).to_uint();
        icache[curr_addr + 3] = sc_bv<32>(inst).range(31,24).to_uint();

        pc_max += 1;
        curr_addr += 4;
    }

    fclose(fp);
}

void
InstFetcher::sendInst() {
    while (true) {
        if (pc_max == 0 || pc == pc_max)
            break;

        tlm::tlm_generic_payload *transaction_ptr = new tlm::tlm_generic_payload();
        transaction_ptr->set_data_ptr(icache + 4 * pc);

        sc_time delay = SC_ZERO_TIME;

        initiator_socket->b_transport(*transaction_ptr, delay);

        gp_status = transaction_ptr->get_response_status();

        if (gp_status == tlm::TLM_OK_RESPONSE) {
            std::cout << "InstFetcher send data success" << std::endl;

            pc += 1;

            wait(SC_ZERO_TIME);
        } else {
            std::cout << "TLM_OK_RESPONSE_NOT" << std::endl;
        }
    }
}

InstFetcher::~InstFetcher() {
    if (icache) delete icache;
}
